home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / othergnu / ispell.zoo / good.c < prev    next >
C/C++ Source or Header  |  1990-03-06  |  14KB  |  780 lines

  1. /* -*- Mode:Text -*- */
  2.  
  3. /*
  4.  * good.c - see if a word or its root word
  5.  * is in the dictionary.
  6.  *
  7.  * Pace Willisson, 1983
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include "config.h"
  13. #include "ispell.h"
  14.  
  15. extern struct dent *lookup();
  16. extern char *index();
  17.  
  18. static int wordok;
  19. static char *orig_word;
  20.  
  21. extern int cflag;
  22.  
  23. good (w)
  24. char *w;
  25. {
  26.     char nword[100];
  27.     register char *p, *q;
  28.     register n;
  29.  
  30.     /*
  31.     ** Make an uppercase copy of the word we are checking.
  32.     */
  33.     for (p = w, q = nword; *p; p++, q++) {
  34.         if (mylower (*p))
  35.             *q = toupper (*p);
  36.         else
  37.             *q = *p;
  38.     }
  39.     *q = 0;
  40.  
  41.     rootword[0] = 0;
  42.  
  43.     if (cflag) {
  44.         printf ("%s\n", w);
  45.         orig_word = w;
  46.     }
  47.     else if (lookup (nword, q - nword, 1) != NULL) {
  48. #ifdef CAPITALIZE
  49.         return cap_ok (w, lastdent);
  50. #else
  51.         return (1);
  52. #endif
  53.     }
  54.  
  55.     /* try stripping off suffixes */
  56.  
  57.     n = strlen (w);
  58.     if (n == 1)
  59.         return (1);
  60.  
  61.     if (n < 4)
  62.         return 0;
  63.  
  64.     wordok = 0;
  65.  
  66.     /* this part from 'check.mid' */
  67.     switch (q[-1]) {
  68.     case 'D': d_ending (nword,n); break;    /* FOR "CREATED", "IMPLIED", "CROSSED" */
  69.     case 'T': t_ending (nword,n); break;    /* FOR "LATEST", "DIRTIEST", "BOLDEST" */
  70.     case 'R': r_ending (nword,n); break;    /* FOR "LATER", "DIRTIER", "BOLDER" */
  71.     case 'G': g_ending (nword,n); break;    /* FOR "CREATING", "FIXING" */
  72.     case 'H': h_ending (nword,n); break;    /* FOR "HUNDREDTH", "TWENTIETH" */
  73.     case 'S': s_ending (nword,n); break;    /* FOR ALL SORTS OF THINGS ENDING IN "S" */
  74.     case 'N': n_ending (nword,n); break;    /* "TIGHTEN", "CREATION", "MULIPLICATION" */
  75.     case 'E': e_ending (nword,n); break;    /* FOR "CREATIVE", "PREVENTIVE" */
  76.     case 'Y': y_ending (nword,n); break;    /* FOR "QUICKLY" */
  77.     default:
  78.         break;
  79.     }
  80.     
  81.     if (wordok) {
  82.         strcpy (rootword, lastdent->word);
  83. #ifdef CAPITALIZE
  84.         return cap_ok (w, lastdent);
  85. #else
  86.         return 1;
  87. #endif
  88.     }
  89.     return 0;
  90. }
  91.  
  92. #ifdef CAPITALIZE
  93. cap_ok (word, dent)
  94. register char *word;
  95. register struct dent *dent;
  96. {
  97.     register char *dword;
  98.     register char *w;
  99.     int wcount;
  100.  
  101.     /*
  102.     ** All caps is always legal.
  103.     */
  104.     for (dword = word;  *dword;  dword++) {
  105.         if (mylower (*dword))
  106.             break;
  107.     }
  108.     if (*dword == '\0')
  109.         return 1;        /* It was all caps */
  110.     if (dent->allcaps)
  111.         return 0;        /* Not all caps and required to be */
  112.     if (dent->followcase) {
  113.         /*
  114.         ** It's a followcase word.  The correct capitalizations are
  115.         ** found following the main dent word.  When we find a
  116.         ** mismatch between letters, we assume we are in the suffix,
  117.         ** and begin insisting on the same case as the last letter
  118.         ** that matched.
  119.         */
  120.         dword = dent->word + strlen (dent->word) + 1;
  121.         wcount = *dword++ & 0xFF;
  122.         while (--wcount >= 0) {
  123.             dword++;            /* Skip over keep flag */
  124.             for (w = word;  *w;  w++, dword++) {
  125.             if (*dword != *w) {
  126.                 /* Begin suffix processing.  */
  127.                 if (myupper (dword[-1])) {
  128.                 while (*w  &&  !mylower (*w))
  129.                     w++;
  130.                 if (*w == '\0')
  131.                     return 1;
  132.                 }
  133.                 else {
  134.                 while (*w  &&  !myupper (*w))
  135.                     w++;
  136.                 if (*w == '\0')
  137.                     return 1;
  138.                 }
  139.                 break;
  140.             }
  141.             }
  142.             if (*w == '\0')
  143.             return 1;
  144.             while (*dword++)    /* Skip to next prototype */
  145.             ;
  146.         }
  147.     }
  148.     /*
  149.     ** If it's a capitalize word, and the first letter is lowercase,
  150.     ** it's illegal.  Note that all-lowercase followcase words will
  151.     ** be found by the string scan above.
  152.     */
  153.     if (dent->capitalize  &&  mylower (*word))
  154.         return 0;
  155.     /*
  156.     ** If it's not a followcase word, or if the capitalize flag is set,
  157.     ** capitalization (e.g. at the beginning of a sentence) is always
  158.     ** legal.  All-lowercase is also legal for non-followcase words.
  159.     */
  160.     if (!dent->followcase  ||  dent->capitalize) {
  161.         for (dword = word + 1;  *dword;  dword++) {
  162.             if (myupper (*dword))
  163.                 break;
  164.         }
  165.         if (*dword == '\0')
  166.             return 1;    /* It was all-lower or capitalized */
  167.     }
  168.     return 0;            /* Word has a bad mix of cases */
  169. }
  170. #endif
  171.  
  172. flagpr (w, flag, modpoint)
  173. register char *w;
  174. int flag;
  175. register char *modpoint;    /* Must be in w and greater than w */
  176. {
  177.     register char *orig;
  178.  
  179.     /*
  180.     ** We refuse to print if the case at and after modpoint isn't
  181.     ** consistent with the case just before there.  This prevents
  182.     ** things like "OEM's" from being turned into OEM/M, which in
  183.     ** turn will only accept "OEM'S".
  184.     */
  185.     orig = orig_word + (modpoint - w);
  186.     if (myupper(orig[-1])) {
  187.         while (*orig) {
  188.             if (mylower (*orig++))
  189.                 return;
  190.         }
  191.     }
  192.     else {
  193.         while (*orig) {
  194.             if (myupper (*orig++))
  195.                 return;
  196.         }
  197.     }
  198.     /* Case is ok.  Now print it. */
  199.     for (orig = orig_word;  *w  &&  w < modpoint;  orig++, w++)
  200.         putchar (*orig);
  201.     if (myupper (orig[-1]))
  202.         printf ("%s", w);
  203.     else {
  204.         for (  ;  *w;  w++) {
  205.             if (myupper (*w))
  206.                 putchar (tolower (*w));
  207.             else
  208.                 putchar (*w);
  209.         }
  210.     }
  211.     printf ("/%c\n", flag);
  212. }
  213.  
  214. g_ending (w,n)
  215. register char *w;
  216. register int n;
  217. {
  218.     register char *p;
  219.     register struct dent *dent;
  220.  
  221.     p = w + n - 3;    /* if the word ends in 'ing', then *p == 'i' */
  222.     
  223.     if (strcmp (p, "ING") != 0)
  224.         return;
  225.  
  226.     *p = 'E';    /* change I to E, like in CREATING */
  227.     *(p+1) = 0;
  228.     n -= 2;
  229.  
  230.     if (n < 2)
  231.         return;
  232.  
  233.     if (cflag)
  234.         flagpr (w, 'G', p);
  235.     else if ((dent = lookup (w, n, 1)) != NULL
  236.       &&  dent->g_flag) {
  237.         wordok = 1;
  238.         return;
  239.     }
  240.  
  241.  
  242.     *p = 0;
  243.     n--;
  244.  
  245.     if (n < 2)
  246.         return;
  247.  
  248.     if (p[-1] == 'E')
  249.         return;    /* this stops CREATEING */
  250.  
  251.     if (cflag)
  252.         flagpr (w, 'G', p);
  253.     else if ((dent = lookup (w, n, 1)) != NULL) {
  254.         if (dent->g_flag)
  255.             wordok = 1;
  256.         return;
  257.     }
  258.     return;
  259. }
  260.  
  261. d_ending (w,n)
  262. register char *w;
  263. register n;
  264. {
  265.     register char *p;
  266.     register struct dent *dent;
  267.  
  268.     p = w + n - 2;
  269.  
  270.     if (strcmp (p, "ED") != 0)
  271.         return;
  272.  
  273.     p[1] = 0;    /* kill 'D' */
  274.     n--;
  275.  
  276.     if (cflag)
  277.         flagpr (w, 'D', p + 1);
  278.     else if ((dent = lookup (w, n, 1)) != NULL) { /* eg CREATED */
  279.         if (dent->d_flag) {
  280.             wordok = 1;
  281.             return;
  282.         }
  283.     }
  284.  
  285.     if (n < 3)
  286.         return;
  287.  
  288.     p[0] = 0;
  289.     n--;
  290.     p--;
  291.  
  292.     /* ED is now completely gone */
  293.  
  294.     if (p[0] == 'I' && !vowel (p[-1])) {
  295.         p[0] = 'Y';
  296.         if (cflag)
  297.             flagpr (w, 'D', p);
  298.         else if ((dent = lookup (w, n, 1)) != NULL
  299.             &&  dent->d_flag) {
  300.             wordok = 1;
  301.             return;
  302.         }
  303.         p[0] = 'I';
  304.     }
  305.  
  306.     if ((p[0] != 'E' && p[0] != 'Y') ||
  307.         (p[0] == 'Y' && vowel (p[-1]))) {
  308.         if (cflag)
  309.             flagpr (w, 'D', p + 1);
  310.         else if ((dent = lookup (w, n, 1)) != NULL) {
  311.             if (dent->d_flag)
  312.                 wordok = 1;
  313.             return;
  314.         }
  315.     }
  316. }
  317.  
  318. t_ending (w,n)
  319. register char *w;
  320. register n;
  321. {
  322.  
  323.     register char *p;
  324.     register struct dent *dent;
  325.  
  326.     p = w + n - 3;
  327.  
  328.     if (strcmp (p, "EST") != 0)
  329.         return;
  330.  
  331.     p[1] = 0;    /* kill "ST" */
  332.     n -= 2;
  333.  
  334.     if (cflag)
  335.         flagpr (w, 'T', p);
  336.     else if ((dent = lookup (w, n, 1)) != NULL
  337.         &&  dent->t_flag) {
  338.         wordok = 1;
  339.         return;
  340.     }
  341.  
  342.     if (n < 3)
  343.         return;
  344.  
  345.     p[0] = 0;    /* kill 'E' */
  346.     n--;
  347.     p--;
  348.  
  349.     /* EST is now completely gone */
  350.  
  351.     if (p[0] == 'I' && !vowel (p[-1])) {
  352.         p[0] = 'Y';
  353.         if (cflag)
  354.             flagpr (w, 'T', p);
  355.         else if ((dent = lookup (w, n, 1)) != NULL
  356.             &&  dent->t_flag) {
  357.             wordok = 1;
  358.             return;
  359.         }
  360.         p[0] = 'I';
  361.     }
  362.  
  363.     if ((p[0] != 'E' && p[0] != 'Y') ||
  364.         (p[0] == 'Y' && vowel (p[-1]))) {
  365.         if (cflag)
  366.             flagpr (w, 'T', p + 1);
  367.         else if ((dent = lookup (w, n, 1)) != NULL) {
  368.             if (dent->t_flag)
  369.                 wordok = 1;
  370.             return;
  371.         }
  372.     }
  373.  
  374. }
  375.  
  376.  
  377. r_ending (w,n)
  378. register char *w;
  379. register n;
  380. {
  381.     register char *p;
  382.     register struct dent *dent;
  383.  
  384.     p = w + n - 2;
  385.  
  386.     if (strcmp (p, "ER") != 0)
  387.         return;
  388.  
  389.     p[1] = 0;    /* kill 'R' */
  390.     n--;
  391.  
  392.     if (cflag)
  393.         flagpr (w, 'R', p + 1);
  394.     else if ((dent = lookup (w, n, 1)) != NULL
  395.         &&  dent->r_flag) {
  396.         wordok = 1;
  397.         return;
  398.     }
  399.  
  400.     if (n < 3)
  401.         return;
  402.  
  403.     p[0] = 0;    /* kill 'E' */
  404.     n--;
  405.     p--;
  406.  
  407.     /* ER is now completely gone */
  408.  
  409.     if (p[0] == 'I' && !vowel (p[-1])) {
  410.         p[0] = 'Y';
  411.         if (cflag)
  412.             flagpr (w, 'R', p);
  413.         else if ((dent = lookup (w, n, 1)) != NULL
  414.             &&  dent->r_flag) {
  415.             wordok = 1;
  416.             return;
  417.         }
  418.         p[0] = 'I';
  419.     }
  420.  
  421.     if ((p[0] != 'E' && p[0] != 'Y') ||
  422.         (p[0] == 'Y' && vowel (p[-1]))) {
  423.         if (cflag)
  424.             flagpr (w, 'R', p + 1);
  425.         else if ((dent = lookup (w, n, 1)) != NULL) {
  426.             if (dent->r_flag)
  427.                 wordok = 1;
  428.             return;
  429.         }
  430.     }
  431.  
  432. }
  433.  
  434. h_ending (w,n)
  435. register char *w;
  436. register n;
  437. {
  438.     register char *p;
  439.     register struct dent *dent;
  440.  
  441.     p = w + n - 2;
  442.  
  443.     if (strcmp (p, "TH") != 0)
  444.         return;
  445.  
  446.     *p = 0;        /* kill "TH" */
  447.     n -= 2;
  448.  
  449.     p -= 2;
  450.  
  451.     if (p[1] != 'Y') {
  452.         if (cflag)
  453.             flagpr (w, 'H', p + 2);
  454.         else if ((dent = lookup (w, n, 1)) != NUL